package com.ruoyi.message.utils;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.ruoyi.common.core.constant.SmsConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.message.domain.AlismsConfig;
import com.ruoyi.message.domain.MsgSms;
import com.ruoyi.message.domain.MsgSmsTpl;
import com.ruoyi.message.service.IAlismsConfigService;
import com.ruoyi.message.service.IMsgSmsService;
import com.ruoyi.message.service.IMsgSmsTplService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class AliSMSService {

    @Autowired
    RedisService redisService;

    @Autowired
    IMsgSmsTplService msgSmsTplService;

    @Autowired
    IAlismsConfigService alismsConfigService;

    @Autowired
    IMsgSmsService iMsgSmsService;

    /**
     * 发送短信验证码
     */
    public R sendVerifyCode(String phone) {
        // 判断验证码是否过于频繁
        String code = redisService.getCacheObject(SmsConstants.CACHE_SMS_VERFY_CODE + phone);
        if(code != null) {
            return R.fail("操作过于频繁");
        }
        code = RandomUtil.randomNumbers(4);

        Map<String, String> params = new HashMap<>();
        params.put("code", code);

        return send(SmsConstants.SMS_TYPE_VERIFY, phone, params);
    }

    /**
     * 发送车辆异常离线通知
     */
    public R sendOutMassage(String phone, String plate) {
        Map<String,String> params = new HashMap<>();
        params.put("plate", plate);

        return send(SmsConstants.SMS_TYPE_VERIFY_GIS, phone, params);
    }

    /**
     * 发送注册信息
     */
    public R sendRegist(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        String name = jsonObject.getString("name");
        String phone = jsonObject.getString("phone");
        String password = jsonObject.getString("password");

        Map<String,String> params = new HashMap<>();
        params.put("name", name);
        params.put("phone", phone);
        params.put("password", password);

        return send(SmsConstants.SMS_TYPE_REGIST, phone, params);
    }

    /**
     * 发送申请通过信息
     */
    public R sendAudit(String json) {
        SimpleDateFormat f = new SimpleDateFormat( "yyyy-MM-dd HH:mm");
        JSONObject jsonObject = JSONObject.parseObject(json);
        String phone = jsonObject.getString("phone");
        String applyType = jsonObject.getString("applyType");

        Map<String,String> params = new HashMap<>();
        params.put("phone", phone);
        params.put("applyType", applyType);
        params.put("submitTime", f.format(new Date()));

        return send(SmsConstants.SMS_TYPE_AUDIT, phone, params);
    }

    /**
     * 发送申请通过信息
     */
    public R sendReject(String json) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        String phone = jsonObject.getString("phone");
        String applyType = jsonObject.getString("applyType");

        Map<String,String> params = new HashMap<>();
        params.put("phone", phone);
        params.put("applyType", applyType);

        return send(SmsConstants.SMS_TYPE_REJECT, phone, params);
    }

    /**
     *
     * @param msgTplType
     * @param phone
     * @param params
     * @return
     */
    private R send(String msgTplType, String phone, Map<String, String> params) {
        // 获取模板
        MsgSmsTpl msgSmsTpl = msgSmsTplService.getSMSTpl(msgTplType);
        if(StringUtils.isNull(msgSmsTpl)) {
            return R.fail("获取短信模板失败");
        }

        AlismsConfig config = alismsConfigService.getAlismsConfig();

        // 发送
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", config.getAccessKey(), config.getAcessSecret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);
        request.setDomain("dysmsapi.aliyuncs.com");
        request.setAction("SendSms");
        request.setVersion("2017-05-25");
        request.putQueryParameter("SignName", config.getSign());
        request.putQueryParameter("RegionId", config.getRegion());
        request.putQueryParameter("TemplateCode", msgSmsTpl.getCode());
        request.putQueryParameter("PhoneNumbers", phone);
        request.putQueryParameter("TemplateParam", JSONObject.toJSONString(params));

        // 保存发送记录
        MsgSms sms = new MsgSms();
        sms.setCreateTime(new Date());
        sms.setMessage(msgSmsTpl.getContent());
        sms.setParams(JSONObject.toJSONString(params));
        sms.setPhone(phone);
        sms.setType(msgTplType);
        sms.setStatus(2);
        try {
            CommonResponse response = client.getCommonResponse(request);
            log.info(response.getData());
            JSONObject result= JSONObject.parseObject(response.getData());
            if("OK".equals(result.getString("Code"))) {
                setCache(msgTplType, phone, params.get("code"));
                sms.setStatus(1);
                iMsgSmsService.save(sms);
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        iMsgSmsService.save(sms);
        return R.fail();
    }

    /**
     * 保存缓存
     * @param msgTplType  短信模板类型
     * @param phone  手机号
     * @param value
     */
    private void setCache(String msgTplType, String phone, String value) {
        switch (msgTplType) {
            case SmsConstants.SMS_TYPE_VERIFY:
                redisService.setCacheObject(SmsConstants.CACHE_SMS_VERFY_CODE + phone, value, 5L, TimeUnit.MINUTES);
                break;
            default:
                break;
        }
    }

}
